home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample PMSAM / PMSAM Framework / RoboSamSlot / CTBChannel.cp < prev    next >
Encoding:
Text File  |  1995-07-28  |  23.8 KB  |  1,168 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CTBChannel.cp
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Written by:    Tim Harnett
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <33>      3/6/95    TMH        adapt to use Symantic compiler
  13.         <32>     2/27/95    TMH        adapt to use ETO16 universal headers
  14.         <31>     2/21/95    TMH        metrowerks compatiblity changes
  15.         <30>     2/15/95    TMH        moved gEnableIOTrace
  16.         <29>    12/16/94    TMH        fix so no error is logged when server not available
  17.         <28>    12/12/94    TMH        use of gCurrentThread->Yield()
  18.         <27>    11/17/94    TMH        fixes to wakeup thread
  19.         <26>    11/10/94    TMH        use StopForIO
  20.         <25>     11/8/94    TMH        changes to support async P3 thread
  21.         <24>     11/2/94    JHB        Adding support for Sending eWorld Mail
  22.         <23>     11/2/94    TMH        IO trace stuff
  23.         <22>     11/2/94    TMH        added no carrier detect stuff, and WriteBytes
  24.         <21>    10/28/94    TMH        Open, Read etc return osErr instead of fail
  25.         <20>    10/28/94    TMH        made async and X25 work better
  26.         <19>    10/26/94    TMH        some tweaks with the asynchronous stuff
  27.         <18>    10/25/94    TMH        made open,close, read & write asynchronous
  28.         <15>    10/24/94    JHB        Correct CMRead ASSERT
  29.         <14>    10/21/94    TMH        created TModemChannel and TX25Channel
  30.         <12>    10/20/94    TMH        cleaned up ICTBChannel
  31.         <11>    10/20/94    TMH        cleaned up ICTBChannel
  32.         <10>    10/18/94    TMH        pass external slot to ICTBChannel, some clean up
  33.         <10>    10/18/94    TMH        pass external slot to ICTBChannel, some clean up
  34.  
  35.     To Do:
  36. */
  37.  
  38.  
  39. #ifndef __ERRORS__
  40. #include "Errors.h"
  41. #endif
  42.  
  43. #include    <String.h>
  44. #include    <Strings.h>
  45. #include    <StdIO.h>
  46.  
  47.  
  48. #ifndef __RESOURCES__
  49. #include "Resources.h"
  50. #endif
  51.  
  52. #ifndef __CRecordID__
  53. #include "CRecordID.h"
  54. #endif
  55.  
  56. #ifndef __CommonResources__
  57. #include "CommonResources.h"
  58. #endif
  59.  
  60. #ifndef __CResourceIterator__
  61. #include "CResourceIterator.h"
  62. #endif
  63.  
  64. #ifndef __CAttribute__
  65. #include "CAttribute.h"
  66. #endif
  67.  
  68. #ifndef __PMSAMResources__
  69. #include "PMSAMResources.h"
  70. #endif
  71.  
  72. #ifndef __PMSAMResourceIds__
  73. #include "PMSAMResourceIDs.h"
  74. #endif
  75.  
  76. #ifndef    _CTBCHANNEL_
  77. #include    "CTBChannel.h"
  78. #endif
  79.  
  80. #ifndef    __MSAMSlot__
  81. #include    "MSAMSlot.h"
  82. #endif
  83.  
  84. #ifndef __Debug__
  85. #include "Debug.h"
  86. #endif
  87.  
  88. #ifndef __UFAILURE__
  89. #include "UFailure.h"
  90. #endif
  91.  
  92. #ifndef __TThread__
  93. #include "TThread.h"
  94. #endif
  95. #ifndef __Globals__
  96. #include "Globals.h"
  97. #endif
  98.             
  99. extern Boolean gEnableIOTrace;        // set from resource
  100.         CFile        gReadCaptureFile;
  101.         CFile        gWriteCaptureFile;
  102.         
  103. void EnableIOCapture();        // the compiler insists!
  104. void EnableIOCapture()
  105. {
  106.     
  107.     Str255 uniqueName;
  108.     long now = TickCount();
  109.     CFolder    traceFolder;
  110.     
  111.     OSErr osErr = FocHFSHeirarchyFromResource(kTraceFolderResID,traceFolder);
  112.     ASSERTNOERR(osErr);
  113.     if( osErr == 0 ) {
  114.  
  115.         FileSpecResource** fileSpec = (FileSpecResource**)::GetResource('file',kReadCaptureFileResID);
  116.         ASSERT(fileSpec);
  117.         if( fileSpec == 0 )
  118.             return;
  119.             
  120.  
  121.         uniqueName[0] = sprintf((char*)&uniqueName[1],"%.20P%08x",(*fileSpec)->filename,now);        // concat time stamp with name.
  122.         gReadCaptureFile.SetFSSpec(-1,traceFolder.DirID(),uniqueName);
  123.         OSErr osErr = gReadCaptureFile.Create((*fileSpec)->fileCreator,(*fileSpec)->fileType);
  124.         ASSERTNOERR(osErr);
  125.         osErr = gReadCaptureFile.Open(fsWrPerm);
  126.         ASSERTNOERR(osErr);
  127.  
  128.  
  129.         fileSpec = (FileSpecResource**)::GetResource('file',kWriteCaptureFileResID);
  130.         ASSERT(fileSpec);
  131.         if( fileSpec == 0 )
  132.             return;
  133.             
  134.  
  135.         uniqueName[0] = sprintf((char*)&uniqueName[1],"%.20P%08x",(*fileSpec)->filename,now);        // concat time stamp with name.
  136.         gWriteCaptureFile.SetFSSpec(-1,traceFolder.DirID(),uniqueName);
  137.         osErr = gWriteCaptureFile.Create((*fileSpec)->fileCreator,(*fileSpec)->fileType);
  138.         ASSERTNOERR(osErr);
  139.         osErr = gWriteCaptureFile.Open(fsWrPerm);
  140.         ASSERTNOERR(osErr);
  141.  
  142.  
  143.  
  144.     }
  145.  
  146.  
  147.  
  148. }
  149.  
  150.  
  151. //----------------------------------------
  152. //    TCTBChannel
  153. //----------------------------------------
  154.  
  155. #pragma segment CTBChannel
  156.  
  157. TCTBChannel::TCTBChannel ()
  158. {
  159.  
  160.     fExternalSlot = 0;
  161.     fConnH = 0;
  162.     fWakeupThread = 0;
  163.     
  164.  
  165.         //    Configuration  -- will be overridden by resource values
  166.         
  167.         
  168.     fReadTimeout = -1;
  169.     fWriteTimeout = -1;
  170.     fOpenTimeout = -1;
  171.     fCloseTimeout = -1;
  172.     
  173.     fOpenASync = kDoSync;
  174.     fCloseASync = kDoSync;
  175.     fReadASync = kDoSync;
  176.     fWriteASync = kDoSync;
  177.     
  178.     fConfigBufSize = 512;
  179.  
  180.  
  181.     fBaudRate = 2400;        // default baud setting, lowest usable
  182.     
  183.  
  184.     memset(&fConnEnvironRec, 0, sizeof(ConnEnvironRec));
  185.     
  186.     for( CMBufFields theCurrField = cmDataIn; theCurrField <= cmRsrvOut; theCurrField++)
  187.         fBufferSizesArray[theCurrField] = 0;
  188.  
  189.  
  190.     fBufferSizesArray[cmDataIn] = fBufferSizesArray[cmDataOut] = 1024;
  191. }
  192.  
  193.  
  194.  
  195. //------------------------------------------------------------------------------------
  196. TCTBChannel::~TCTBChannel ()
  197. {
  198.         
  199.     if (fConnH != 0 )
  200.         CMDispose(fConnH);
  201.  
  202.     if( fWakeupThread != 0 ) {    
  203.         ASSERT(fWakeupThread->GetThreadState() == kStoppedThreadState);
  204.         delete fWakeupThread;
  205.     }
  206.  
  207.     if( fCTBIdleThread != 0 ) {    
  208.         ASSERT(fCTBIdleThread->GetThreadState() == kStoppedThreadState);
  209.         delete fCTBIdleThread;
  210.     }
  211.  
  212. }
  213.  
  214.  
  215.  
  216. //------------------------------------------------------------------------------------
  217. void TCTBChannel::ICTBChannel(short toolParamResID,StringPtr toolName, TExternalSlot* exSlot)
  218. {
  219.  
  220.     ASSERT(exSlot);
  221.     
  222.  
  223.     FailInfo         fi;
  224.     Try(fi) 
  225.     {
  226.         fExternalSlot = exSlot;
  227.         
  228.         this->SetCTBParametersFromResource(toolParamResID);
  229.  
  230.  
  231.         this->InitializeCTB();
  232.         
  233.         short    theToolProcID = CMGetProcID(toolName);    
  234.         ASSERT( theToolProcID != -1 );
  235.         if (theToolProcID == -1)
  236.             FailOSErr(errUnableToInitCTB);
  237.  
  238.  
  239.         CMRecFlags  theCMFlags = cmData + cmQuiet + cmNoMenus;
  240.         long        myRefCon = 0;
  241.         long        myUserData = 0;
  242.         
  243.         fConnH = CMNew (theToolProcID, theCMFlags, fBufferSizesArray, myRefCon, myUserData);
  244.         if(!fConnH) {
  245.             ASSERT( fConnH != 0 );
  246.             FailMemError();
  247.         }
  248.  
  249.  
  250.             //    The wakeup thread for async IO.
  251.             
  252.         
  253.         TWakeupThread* wakeupThread = new TWakeupThread;
  254.         wakeupThread->IWakeupThread();
  255.         fWakeupThread = wakeupThread;
  256.  
  257.  
  258.             //    Idle thread -- to assure that CMIdle is called.
  259.             
  260.         TCTBIdleThread* idleThread = new TCTBIdleThread;
  261.         idleThread->ICTBIdleThread(this);
  262.         fCTBIdleThread = idleThread;
  263.         
  264.         CMSetRefCon(fConnH,(long) this);
  265.  
  266.             //    If we'll be capturing get a file for it.
  267.  
  268.         if( gEnableIOTrace )
  269.             ::EnableIOCapture();
  270.  
  271.         fi.Success();
  272.         
  273.     } else {
  274.                 
  275.         delete this;
  276.         fi.ReSignal();
  277.             
  278.     }
  279.  
  280.     return;
  281. }
  282.  
  283.  
  284.  
  285. //------------------------------------------------------------------------------------
  286. void    TCTBChannel::Waitfor( short time)
  287. {
  288.     long t=0;
  289.     long timeout;
  290.     
  291.     timeout = TickCount()+time;
  292.     while (TickCount()<timeout) ++t;
  293.     
  294. }
  295.  
  296.  
  297.  
  298. //---------------------------------------------------------------
  299. void TCTBChannel::InitializeCTB()
  300. {
  301.     CMErr theCMErr = InitCM();
  302.     ASSERTNOERR(theCMErr);
  303.  
  304.     if( theCMErr != 0 )
  305.         FailOSErr(errUnableToInitCTB);
  306.         
  307.     
  308.     CTBUErr     theCTBErr = InitCTBUtilities();
  309.     ASSERTNOERR(theCTBErr);
  310.     if( theCTBErr != 0 )
  311.         FailOSErr(errUnableToInitCTB);
  312.  
  313. }
  314.  
  315.  
  316.  
  317. //--------------------------------------------------------------------------------------
  318. OSErr TCTBChannel::Connect(Ptr configString)
  319. {
  320.     ASSERT(configString);
  321.     ASSERT( fCommState != sConnected);
  322.     ASSERT( fCommState != sConnecting );
  323.         
  324.                         
  325.     FailInfo    fi;
  326.     Try(fi) {
  327.  
  328.         fCTBIdleThread->StartThread();
  329.  
  330.         short    setConfigErr = CMSetConfig(fConnH, configString);
  331.         ASSERT(setConfigErr==0);
  332.         if(setConfigErr)
  333.             FailOSErr(errCommConfigParamMissingOrCorrupt);
  334.  
  335.  
  336.         Boolean    hConnValid = CMValidate(fConnH);        // gratuitous 
  337.         ASSERTNOERR(hConnValid);
  338.  
  339.  
  340.         FailOSErr( this->Open() );
  341.  
  342.  
  343.         fConnEnvironRec.version = curConnEnvRecVers;
  344.         CMErr cmErr = CMGetConnEnvirons(fConnH, &fConnEnvironRec);
  345.         ASSERTNOERR(cmErr);
  346.         FailOSErr(cmErr);
  347.  
  348.  
  349.         this->NetworkLogin();
  350.  
  351.         fCommState = sConnected;
  352.  
  353.  
  354.         fi.Success();
  355.  
  356.  
  357.     } else {
  358.     
  359.         if( ::IsCTBError(fi.error) )
  360.             fi.error = errCantOpenCTBConnection;        // what will be reported to the user.
  361.  
  362.  
  363.         this->Close();
  364.         fCTBIdleThread->StopThread();
  365.  
  366.         fCommState = sDisconnected;
  367.  
  368.     }        
  369.  
  370.  
  371.     return fi.error;
  372.  
  373.  
  374. }
  375.  
  376.  
  377. //---------------------------------------------------------------
  378. void TCTBChannel::NetworkLogin( )
  379. {
  380.     
  381.             
  382. }
  383.  
  384.  
  385.  
  386. //--------------------------------------------------------------------------------------
  387. void TCTBChannel::Disconnect()
  388. {
  389.     while( this->IsIOPending() )
  390.         gCurrentThread->Yield();
  391.     
  392.  
  393.     if( this->IsOpen() ) {
  394.         this->KillAllIO();
  395.         this->Close();
  396.     }
  397.     
  398.     fCTBIdleThread->StopThread();
  399.     
  400. }
  401.  
  402.  
  403. //---------------------------------------------------------------------------
  404. Boolean    TCTBChannel::IsIOPending()
  405. {
  406.     CMStatFlags cmStatus = this->GetCMStatus();
  407.  
  408.         
  409.     CMStatFlags pendingFlags =    cmStatusOpening + cmStatusClosing + 
  410.                                 cmStatusDRPend + cmStatusDWPend    +
  411.                                 cmStatusCRPend + cmStatusCWPend    + 
  412.                                 cmStatusARPend + cmStatusAWPend    +
  413.                                 cmStatusBreakPend + cmStatusListenPend;
  414.  
  415.  
  416.         //    Careful here of the small window of execution where the wakeup thread has been started
  417.         //    but has not yet started the threadtoWake, ie. it remains Stopped until IO completion
  418.         //    routine is called.
  419.         
  420.  
  421.     return ((cmStatus & pendingFlags) != 0) || fWakeupThread->Busy();
  422.  
  423.  
  424. }
  425.  
  426.  
  427. //---------------------------------------------------------------------------
  428. Boolean    TCTBChannel::IsOpen()
  429. {
  430.     CMStatFlags cmStatus = this->GetCMStatus();
  431.     return (cmStatus & cmStatusOpen) != 0;
  432. }
  433.  
  434.  
  435. //---------------------------------------------------------------------------
  436. Boolean    TCTBChannel::IsOpenPending()
  437. {
  438.  
  439.     CMStatFlags cmStatus = this->GetCMStatus();
  440.  
  441.         //     Should we be checking all of these?
  442.         
  443.     return (cmStatus & cmStatusOpening) != 0 || fWakeupThread->Busy();
  444. }
  445.  
  446. //---------------------------------------------------------------------------
  447. Boolean    TCTBChannel::IsReadPending()
  448. {
  449.     CMStatFlags cmStatus = this->GetCMStatus();
  450.         
  451.     return (cmStatus & cmStatusDRPend) != 0 || fWakeupThread->Busy();
  452. }
  453.  
  454.  
  455. //---------------------------------------------------------------------------
  456. Boolean    TCTBChannel::IsWritePending()
  457. {
  458.     CMStatFlags cmStatus = this->GetCMStatus();
  459.         
  460.     return (cmStatus & cmStatusDWPend) != 0 || fWakeupThread->Busy();
  461. }
  462.  
  463.  
  464. //---------------------------------------------------------------------------
  465. long TCTBChannel::DataAvail()
  466. {
  467.     long                datacount = 0;
  468.     CMStatFlags            stat;
  469.     CMBufferSizes        counts;
  470.     
  471.     
  472.     CMErr cmErr = CMStatus(fConnH, counts, &stat);
  473.     ASSERTNOERR(cmErr);
  474.     
  475.     if( cmErr == 0 )        
  476.         datacount = counts[cmDataIn];
  477.         
  478.     return datacount;
  479. }
  480.  
  481.  
  482.  
  483. //---------------------------------------------------------------------------
  484. CMStatFlags        TCTBChannel::GetCMStatus()
  485. {
  486.  
  487.     CMStatFlags        statusFlags = 0;
  488.     CMBufferSizes        counts;
  489.     CMErr    cmErr = CMStatus(fConnH, counts, &statusFlags);
  490.     ASSERTNOERR(cmErr);
  491.  
  492.  
  493.     return statusFlags;
  494. }
  495.  
  496.  
  497. //---------------------------------------------------------------------------------
  498. CMErr TCTBChannel::KillAllIO()
  499. {
  500.     short    allIO = cmDataIn+cmDataOut+cmCntlIn+cmCntlOut+cmAttnIn+cmAttnOut;
  501.     
  502.     CMErr cmErr = CMIOKill(fConnH,allIO);
  503.     ASSERTNOERR(cmErr);
  504.     
  505.     return cmErr;
  506.     
  507. }
  508.  
  509.  
  510. //---------------------------------------------------------------------------------
  511. CMErr TCTBChannel::Abort()
  512. {
  513.     
  514.     CMErr cmErr = CMAbort(fConnH);
  515.     ASSERTNOERR(cmErr);
  516.     
  517.     return cmErr;
  518.     
  519. }
  520.  
  521. //--------------------------------------------------------------------------------------
  522. void     TCTBChannel::FlushRead()
  523. {
  524.     ASSERT(!this->IsReadPending());
  525.     
  526.     CMErr cmErr =CMIOKill(fConnH, cmDataIn);
  527.     
  528.     ASSERTNOERR(cmErr);
  529.  
  530. }
  531.  
  532.  
  533. //--------------------------------------------------------------------------------------
  534. void     TCTBChannel::FlushWrite()
  535. {
  536.     ASSERT(!this->IsWritePending());
  537.     
  538.     CMErr cmErr =CMIOKill(fConnH, cmDataOut);
  539.     ASSERTNOERR(cmErr);
  540.     
  541. }
  542.  
  543.  
  544.  
  545. //--------------------------------------------------------------------------
  546. CMErr TCTBChannel::Open()
  547. {
  548.     CMErr cmErr = 0;
  549.     
  550.     if( fOpenASync ) {
  551.     
  552.         fWakeupThread->SetThreadToWake(gCurrentThread);
  553.         ASSERT( fWakeupThread->GetThreadState() == kStoppedThreadState );
  554.         
  555.         CMOpen(fConnH, kDoAsync, &__CTBCompletorProc, this->OpenTimeout());
  556.         
  557.         gCurrentThread->StopForIO();
  558.         
  559.         fWakeupThread->SetThreadToWake(0);
  560.     
  561.         cmErr = (short)(*fConnH)->userData;
  562.         
  563.                 
  564.     } else {
  565.     
  566.         cmErr = CMOpen(fConnH, kDoSync, 0, this->OpenTimeout());
  567.             
  568.     }
  569.     
  570.     
  571.     ASSERTNOERR(cmErr);
  572.     
  573.     return cmErr;
  574.     
  575.         
  576. }
  577.  
  578.  
  579.  
  580. #pragma segment CTBChannel
  581. //--------------------------------------------------------------------------
  582. OSErr TCTBChannel::Close()
  583. {
  584.     CMErr cmErr = 0;
  585.     
  586.     if( fOpenASync ) {
  587.  
  588.  
  589.         fWakeupThread->SetThreadToWake(gCurrentThread);
  590.         ASSERT( fWakeupThread->GetThreadState() == kStoppedThreadState );
  591.         
  592.         CMClose( fConnH, kDoAsync, &__CTBCompletorProc, this->CloseTimeout(), kDontWaitForPending);
  593.         
  594.         gCurrentThread->StopForIO();
  595.         fWakeupThread->SetThreadToWake(0);
  596.         
  597.         cmErr = (short)(*fConnH)->userData;
  598.  
  599.     } else {
  600.     
  601.         cmErr = CMClose( fConnH, kDoAsync, 0, this->CloseTimeout(), kDontWaitForPending);
  602.         
  603.     }
  604.  
  605.     ASSERTNOERR(cmErr);
  606.         
  607.     return cmErr;
  608.     
  609. }
  610.  
  611.  
  612. //-------------------------------------------------------------------------------
  613. CMErr TCTBChannel::Read( char *theBuffer, long bytesToRead, long timeOut)
  614. {
  615.     CMErr cmErr = 0;
  616.     
  617.     if( fReadASync ) {
  618.  
  619.         fWakeupThread->SetThreadToWake(gCurrentThread);
  620.         ASSERT( fWakeupThread->GetThreadState() == kStoppedThreadState );
  621.         
  622.         CMRead(fConnH, theBuffer, &bytesToRead, cmData, kDoAsync, &__CTBCompletorProc, timeOut, &fConnEnvironRec.flags);
  623.         
  624.         gCurrentThread->StopForIO();
  625.         fWakeupThread->SetThreadToWake(0);
  626.         
  627.         cmErr = (short)(*fConnH)->userData;
  628.  
  629.     
  630.     } else {
  631.     
  632.         cmErr = CMRead(fConnH, theBuffer, &bytesToRead, cmData, kDoSync, 0, timeOut, &fConnEnvironRec.flags);
  633.         
  634.     }
  635.  
  636.  
  637.     ASSERTNOERR(cmErr);
  638.     
  639.     if( cmErr == 0 && gEnableIOTrace )
  640.         gReadCaptureFile.Write(theBuffer,bytesToRead);        // ignore errors
  641.         
  642.     
  643.     return cmErr;
  644.     
  645. }
  646.  
  647.  
  648. //-------------------------------------------------------------------------------
  649. CMErr TCTBChannel::Write( char *theBuffer, long bytesToWrite, long timeOut)
  650. {
  651.     CMErr cmErr = 0;
  652.     
  653.     if( fWriteASync ) {
  654.     
  655.         fWakeupThread->SetThreadToWake(gCurrentThread);
  656.         ASSERT( fWakeupThread->GetThreadState() == kStoppedThreadState );
  657.     
  658.         CMWrite(fConnH, theBuffer, &bytesToWrite, cmData, kDoAsync, &__CTBCompletorProc,timeOut, fConnEnvironRec.flags);
  659.     
  660.         gCurrentThread->StopForIO();
  661.         fWakeupThread->SetThreadToWake(0);
  662.         
  663.         cmErr = (short)(*fConnH)->userData;
  664.  
  665.     } else {
  666.     
  667.         cmErr = CMWrite(fConnH, theBuffer, &bytesToWrite, cmData, kDoSync, 0 ,timeOut, fConnEnvironRec.flags);
  668.     }
  669.  
  670.  
  671.     ASSERTNOERR(cmErr);
  672.     
  673.     
  674.     if( cmErr == 0 && gEnableIOTrace )
  675.         gWriteCaptureFile.Write(theBuffer,bytesToWrite);        // ignore errors
  676.         
  677.  
  678.  
  679.     return cmErr;
  680.  
  681. }
  682.  
  683.  
  684.  
  685.  
  686.  
  687. //-------------------------------------------------------------------------------
  688. void TCTBChannel::WriteBytes( void *theBuffer, long bytesToWrite)
  689. {
  690.     FailOSErr( this->Write((char*)theBuffer,bytesToWrite,this->WriteTimeout()) );
  691. }
  692.  
  693.  
  694.  
  695. //-------------------------------------------------------------------------------
  696. pascal void        TCTBChannel::__CTBCompletorProc(ConnHandle  theConnectionHandle)
  697. {
  698.  
  699.     TCTBChannel* thisChannel = (TCTBChannel*) (*theConnectionHandle)->refCon;    
  700.     long a5 = thisChannel->fWakeupThread->GetThreadA5();
  701.     long curA5 = ::SetA5(a5);
  702.  
  703.         
  704.     (*theConnectionHandle)->userData = (*theConnectionHandle)->errCode;
  705.          
  706.     thisChannel->fWakeupThread->StartThreadFromCompletionRoutine();
  707.  
  708.         
  709.     ::SetA5(curA5);
  710.  
  711.         
  712. }
  713.  
  714.  
  715.  
  716. //---------------------------------------------------------------------------------
  717. void TCTBChannel::IdleChannel()
  718. {
  719.     CMStatFlags flags = this->GetCMStatus();
  720.     
  721.     if( flags != 0 )
  722.         CMIdle(fConnH);
  723.  
  724.  
  725. }
  726.  
  727.  
  728. //---------------------------------------------------------------------------------
  729. char TCTBChannel::ReadByte()
  730. {    
  731.     char c;
  732.     FailOSErr( this->Read(&c ,1,this->ReadTimeout() ) );
  733.     return c;
  734. }
  735.  
  736.  
  737. //---------------------------------------------------------------------------------
  738. void TCTBChannel::ReadBytes(char *theBuffer, long bytesToRead )
  739.     FailOSErr( this->Read(theBuffer,bytesToRead,this->ReadTimeout() ) ); 
  740. }
  741.  
  742.  
  743. //-------------------------------------------------------------------------------
  744. char TCTBChannel::WaitFor(char waitFor)
  745. {
  746.  
  747.     char c;
  748.     do {
  749.     
  750.         c =  this->ReadByte();
  751.         ASSERTPRINT( c== waitFor,("CTB waiting for %0X, recieived = %0x\n",waitFor,c) );
  752.         
  753.     } while( c != waitFor );
  754.     
  755.     return c;
  756.     
  757. }
  758.  
  759.  
  760.  
  761. //-------------------------------------------------------------------------------
  762. char TCTBChannel::WaitForOneOf(char *searchString)
  763. {
  764.  
  765.     char c = 0;
  766.     do {
  767.         c = this->ReadByte();
  768.     } while( !strchr(searchString, c) );
  769.  
  770.  
  771.     return c;
  772.  
  773. }
  774.  
  775.  
  776. //------------------------------------------------------------------------------
  777. void    TCTBChannel::WaitForString(char* searchString)
  778. {
  779.  
  780.     char c = 0;
  781.     long matchIndex = 0;    
  782.     
  783.     long searchStringLen = strlen(searchString);
  784.     
  785.     while( matchIndex < searchStringLen ) {
  786.  
  787.         c = this->ReadByte();
  788.  
  789.         if (  c == searchString[matchIndex] )
  790.             matchIndex++;
  791.         else if ( c == searchString[0] )            // does it match from the beginning?
  792.             matchIndex = 1;
  793.         else
  794.             matchIndex = 0;
  795.  
  796.  
  797.     }
  798.     
  799.     
  800.     return;
  801. }
  802.  
  803.  
  804.  
  805. //------------------------------------------------------------------------------
  806. void    TCTBChannel::SendString(char*    sendString)
  807. {
  808.     unsigned long    sendLength = strlen(sendString);
  809.     
  810.     FailOSErr( this->Write( sendString, sendLength, this->WriteTimeout()) );
  811.  
  812. }
  813.  
  814.  
  815.  
  816.  
  817. //-------------------------------------------------------------------------------------
  818. void TCTBChannel::SetCTBParametersFromResource(short resID)
  819. {
  820.  
  821.     CommParameterResource** commParams = (CommParameterResource**)::Get1Resource('ctbp',resID);
  822.     FailNILResource((Handle)commParams);
  823.  
  824.  
  825.     fReadTimeout = (*commParams)->readTimeout == -1 ? -1 : (*commParams)->readTimeout*60;
  826.     fWriteTimeout = (*commParams)->writeTimeout == -1 ? -1 : (*commParams)->writeTimeout*60;
  827.     fOpenTimeout = (*commParams)->openTimeout == -1 ? -1 : (*commParams)->openTimeout*60;
  828.     fCloseTimeout = (*commParams)->closeTimeout == -1 ? -1 : (*commParams)->closeTimeout*60;
  829.  
  830.     fOpenASync  = ((*commParams)->flags & kOpenASync) != 0;
  831.     fCloseASync = ((*commParams)->flags & kCloseASync) != 0;
  832.     fReadASync  = ((*commParams)->flags & kReadASync) != 0;
  833.     fWriteASync = ((*commParams)->flags & kWriteASync) != 0;
  834.  
  835.  
  836.     fConfigBufSize = (*commParams)->configStrBufSize;
  837.     
  838.  
  839.     fBaudRate = (*commParams)->minimumBaudRate;
  840.     
  841.     ReleaseResource((Handle)commParams);
  842.     
  843. }
  844.  
  845.  
  846.  
  847. //---------------------------------
  848. //    T M o d e m C h a n n e l
  849. //---------------------------------
  850.  
  851.  
  852. //----------------------------------------------------------
  853. TModemChannel::TModemChannel()
  854. {
  855.     fAccessNetwork = SPRINTNET;
  856.     
  857.     fNoCarrierDetectRefNum = 0;
  858.     fNoCarrierDetected = false;
  859.  
  860.  
  861. }
  862.  
  863. //----------------------------------------------------------
  864. void TModemChannel::IModemChannel(StringPtr toolName, TExternalSlot* exSlot)
  865. {
  866.  
  867.     this->ICTBChannel(kModemToolParams,toolName, exSlot);
  868.  
  869.  
  870.         //    NO CARRIER Filter
  871.     Str255    noCarrierStr;
  872.     GetIndString(noCarrierStr, kCTBStreamSearchStrings, kNoCarrierStr);
  873.     FailResError();
  874.     fNoCarrierDetectRefNum = CMAddSearch(fConnH,noCarrierStr,0,NoCarrierDetectProc);
  875.  
  876.  
  877. }
  878.  
  879.  
  880.  
  881. //----------------------------------------------------------
  882. void TModemChannel::MakeConnection()
  883. {
  884.     Ptr    configStr =    0;
  885.     
  886.     FailInfo fi;
  887.     Try(fi) {
  888.  
  889.  
  890.         long    buffSize = fConfigBufSize;
  891.         configStr = NewPtr( buffSize );
  892.         FailMemError();
  893.         VOLATILE(configStr);
  894.         
  895.         
  896.             //    Read the attribute that holds the config string.
  897.         Handle rsrc =    ::Get1Resource('rstr',kCTBConfigStrAttrTypeResID);
  898.         FailNILResource(rsrc);
  899.         CAttributeType configStrAttrType( (RStringHandle)rsrc);
  900.  
  901.  
  902.         OSErr osErr = fExternalSlot->ReadSlotAttribute(configStrAttrType,configStr ,buffSize);
  903.         FailOSErr(osErr);
  904.  
  905.  
  906.         FailOSErr (this->Connect(configStr) );
  907.     
  908.         if(configStr != 0 )
  909.             DisposePtr(configStr);
  910.         
  911.         fi.Success();
  912.         
  913.     } else {
  914.     
  915.         if(configStr != 0 )
  916.             DisposePtr(configStr);
  917.         
  918.         fi.ReSignal();
  919.         
  920.     }
  921.  
  922.  
  923. }
  924.  
  925. //------------------------------------------------------------------------------
  926. void TModemChannel::NetworkLogin( )
  927. {
  928.     switch(fAccessNetwork) {
  929.     
  930.     case SPRINTNET:
  931.         this->SprintNetLogin();
  932.     break;
  933.     
  934.     default:
  935.         // if no network, we assume we are connecting direectly to an eWorld modem, no nmetwork login necessary
  936.     break;
  937.         
  938.     };
  939.  
  940.     this->WaitForString("CONNECT");
  941.     
  942.     
  943. }
  944.  
  945.  
  946.  
  947. //-------------------------------------------------------------------------------
  948. pascal void    TModemChannel::NoCarrierDetectProc(ConnHandle  hConn,Ptr /*matchPtr*/, long /*refNum */)
  949. {
  950.  
  951.     TModemChannel* thisChannel = (TModemChannel*) (*hConn)->refCon;    
  952.     thisChannel->fNoCarrierDetected = true;
  953.     
  954. }
  955.  
  956.  
  957. //------------------------------------------------------------------------------
  958. void TModemChannel::SprintNetLogin ()
  959. {
  960.   
  961.     this->Waitfor(300);   // ••Hack•• Cant explain why this is necessary but without it we do not connect, JB
  962.    
  963.     if (this->fBaudRate <= 2400)
  964.         this->SendString("\x0D\x44\x0D");
  965.     else 
  966.         this->SendString("@D\x0D");
  967.  
  968.  
  969.     char c = this->WaitForOneOf("?=@");
  970.     switch ( c ) {
  971.    
  972.     case  '@':           //     we're at Sprintnet's command prompt
  973.         break;
  974.             
  975.     case  '=':           //    support update_800 connections
  976.       
  977.         this->SendString("D1\x0D");
  978.         
  979.         c = this->WaitForOneOf( "?=@");
  980.         switch ( c ) {
  981.         
  982.         case  '@':
  983.                  break;
  984.                  
  985.          case  '=':
  986.             this->SendString("703,555\x0D");
  987.             this->WaitForOneOf("@");
  988.             break;
  989.             
  990.         case '?':
  991.             ASSERTPRINT(false,("Gotta ? in TModemChannel::SprintnetLogin ") );
  992.             FailOSErr(errCantOpenCTBConnection);
  993.             break;
  994.         
  995.         default:    // should NEVER happen
  996.             ASSERTPRINT(false,("Gotta unexpected char in TModemChannel::SprintnetLogin "));
  997.             FailOSErr(errCantOpenCTBConnection);
  998.             break;
  999.         };
  1000.         
  1001.         break;
  1002.         
  1003.     case '?':
  1004.         ASSERTPRINT(false,("Gotta ? in TModemChannel::SprintnetLogin "));
  1005.         FailOSErr(errCantOpenCTBConnection);
  1006.         break;
  1007.         
  1008.     default:        // should NEVER happen
  1009.         ASSERTPRINT(false,("Gotta ? in TModemChannel::SprintnetLogin "));
  1010.         break;
  1011.         
  1012.     }
  1013.  
  1014.  
  1015.    // if we get here, we're at Sprint's command prompt... send our connection address */
  1016.    this->FlushRead();
  1017.    
  1018.    Handle rsrc = ::Get1Resource('cstr',kSprintConnectAddrResID);
  1019.    FailNILResource(rsrc);
  1020.    char    addrBuf[256];
  1021.    BlockMove((Ptr)*rsrc,(Ptr)addrBuf,strlen((char const *)*rsrc)+1);
  1022.    
  1023.     this->SendString(addrBuf);
  1024.     fCommState = sConnecting;
  1025.  
  1026.  
  1027.  
  1028.    return;
  1029. }
  1030.  
  1031.  
  1032.  
  1033. //---------------------------------
  1034. //    T X 2 5 C h a n n e l
  1035. //---------------------------------
  1036.  
  1037.  
  1038.  
  1039. //----------------------------------------------------------
  1040. TX25Channel::TX25Channel()
  1041. {
  1042. }
  1043.  
  1044.  
  1045. //----------------------------------------------------------
  1046. void TX25Channel::IX25Channel(StringPtr toolName, TExternalSlot* exSlot)
  1047. {
  1048.     this->ICTBChannel(kX25ToolParams,toolName, exSlot);
  1049.  
  1050. }
  1051.  
  1052. //----------------------------------------------------------
  1053. void TX25Channel::NetworkLogin( )
  1054. {
  1055.  
  1056.     fCommState = sConnecting;
  1057.     char charFound = this->WaitForOneOf("\x11");        
  1058.  
  1059. }
  1060.  
  1061. //----------------------------------------------------------
  1062. void TX25Channel::MakeConnection()
  1063. {
  1064.  
  1065.     //    We try every 'mpad' resource before giving up.  There is a
  1066.     //    'mpad' resource for every MacX25 server we should try.
  1067.     
  1068.     
  1069.     Ptr    configStr = 0;
  1070.  
  1071.     FailInfo    fi;
  1072.     Try(fi) {
  1073.     
  1074.         long    buffSize = fConfigBufSize;
  1075.         configStr = NewPtr( buffSize );            // Caller is responsible for Disposing.
  1076.         FailMemError();
  1077.         VOLATILE(configStr);
  1078.  
  1079.  
  1080.         OSErr osErr = errCommConfigParamMissingOrCorrupt;        // in case there are NO 'mpad' resources
  1081.         CResourceIterator iter('mpad');
  1082.         for( Handle rsrc = iter.FirstResource(); iter.More(); rsrc = iter.NextResource() ) {
  1083.         
  1084.             strcpy((char*)configStr,(char*)*rsrc);
  1085.             osErr = this->Connect(configStr);
  1086.             if( osErr == 0 )
  1087.                 break;
  1088.                 
  1089.             //    else try the next server...
  1090.             extern Boolean gAssertsEnabled;
  1091.             if( gAssertsEnabled ) {
  1092.                 Str255    rsrcName;
  1093.                 rsrcName[0] = 0;
  1094.                 short resID;
  1095.                 ResType resType;
  1096.                 GetResInfo(rsrc,&resID,&resType,rsrcName);
  1097.                 ASSERTPRINT(false,("MacX25Server %P not available.\n",rsrcName) );
  1098.             }
  1099.             
  1100.         
  1101.         }
  1102.         
  1103.         FailOSErr(osErr);
  1104.  
  1105.  
  1106.  
  1107.         if(configStr != 0 )
  1108.             DisposePtr(configStr);
  1109.  
  1110.         
  1111.         fi.Success();
  1112.         
  1113.         
  1114.     } else {
  1115.     
  1116.         if(configStr != 0 )
  1117.             DisposePtr(configStr);
  1118.  
  1119.  
  1120.         fi.ReSignal();
  1121.         
  1122.     }
  1123.     
  1124.     
  1125. }
  1126.  
  1127.  
  1128.  
  1129. //-------------------------------------
  1130. //     T C T B I d l e T h r e a d
  1131. //--------------------------------------
  1132.  
  1133.  
  1134. //-------------------------------------------------------------------------------
  1135. TCTBIdleThread::TCTBIdleThread()
  1136. {
  1137.  
  1138.     fCTBChannel = 0;
  1139. }
  1140.  
  1141.  
  1142. //-------------------------------------------------------------------------------
  1143. void TCTBIdleThread::ICTBIdleThread(TCTBChannel* ctbChannel)
  1144. {
  1145.     this->ICooperativeThread('cidl',kCTBIdleThreadStackSize,kNewSuspend);        // start in ::Connect
  1146.     fCTBChannel = ctbChannel;
  1147. }
  1148.  
  1149. //-------------------------------------------------------------------------------
  1150. void* TCTBIdleThread::ThreadMain()
  1151. {
  1152.  
  1153.     while( true ) {
  1154.         
  1155.         FailInfo fi;
  1156.         Try(fi) {
  1157.             fCTBChannel->IdleChannel();
  1158.             this->Yield();    
  1159.             fi.Success();
  1160.         }
  1161.         
  1162.     }
  1163.     
  1164.     return this;        
  1165. }
  1166.  
  1167.